{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Importing Required Libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\users\\thushan\\documents\\python_virtualenvs\\tensorflow_venv\\lib\\site-packages\\h5py\\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "import os\n",
    "import matplotlib.pyplot as plt\n",
    "# Config the matplotlib backend as plotting inline in IPython\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sigmoid Example - Feeding inputs with a Placeholder\n",
    "Here we calculate the sigmoid example by feeding in inputs with a placeholder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.48335528 0.5232182  0.5201818  0.44878143 0.50730604]]\n"
     ]
    }
   ],
   "source": [
    "# Defining the graph and session\n",
    "graph = tf.Graph() # Creates a graph\n",
    "session = tf.InteractiveSession(graph=graph) # Creates a session\n",
    "\n",
    "# Building the graph\n",
    "\n",
    "# A placeholder is an symbolic input\n",
    "x = tf.placeholder(shape=[1,10],dtype=tf.float32,name='x') \n",
    "\n",
    "# Variable\n",
    "W = tf.Variable(tf.random_uniform(shape=[10,5], minval=-0.1, maxval=0.1, dtype=tf.float32),name='W') \n",
    "# Variable\n",
    "b = tf.Variable(tf.zeros(shape=[5],dtype=tf.float32),name='b') \n",
    "\n",
    "h = tf.nn.sigmoid(tf.matmul(x,W) + b) # Operation to be performed\n",
    "\n",
    "# Executing operations and evaluating nodes in the graph\n",
    "tf.global_variables_initializer().run() # Initialize the variables\n",
    "\n",
    "# Run the operation by providing a value to the symbolic input x\n",
    "h_eval = session.run(h,feed_dict={x: np.random.rand(1,10)}) \n",
    "print(h_eval)\n",
    "session.close() # Frees all the resources associated with the session\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Feeding inputs as Tensorflow tensors\n",
    "\n",
    "Now we make the same calculations with the input as an immutable tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.57097197 0.49519295 0.5462523  0.49257272 0.4984648 ]]\n"
     ]
    }
   ],
   "source": [
    "# Defining the graph and session\n",
    "graph = tf.Graph() # Creates a graph\n",
    "session = tf.InteractiveSession(graph=graph) # Creates a session\n",
    "\n",
    "# Building the graph\n",
    "\n",
    "# A pre-loaded input\n",
    "x = tf.constant(value=[[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]],dtype=tf.float32,name='x') \n",
    "\n",
    "# Variable\n",
    "W = tf.Variable(tf.random_uniform(shape=[10,5], minval=-0.1, maxval=0.1, dtype=tf.float32),name='W') \n",
    "# Variable\n",
    "b = tf.Variable(tf.zeros(shape=[5],dtype=tf.float32),name='b') \n",
    "\n",
    "h = tf.nn.sigmoid(tf.matmul(x,W) + b) # Operation to be performed\n",
    "\n",
    "# Executing operations and evaluating nodes in the graph\n",
    "tf.global_variables_initializer().run() # Initialize the variables\n",
    "\n",
    "# Run the operation without feed_dict\n",
    "h_eval = session.run(h) \n",
    "print(h_eval)\n",
    "\n",
    "# Closes the session to free any held resources by the session\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Creating a Tensorflow Data Pipeline\n",
    "We now create a data pipleline to read inputs. Data pipeline is an efficient way of reading data when you have to read lots of data stored externally."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "File test1.txt found.\n",
      "File test2.txt found.\n",
      "File test3.txt found.\n",
      "========== Step 0 ==========\n",
      "Evaluated data (x)\n",
      "[[0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]\n",
      " [0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]\n",
      " [0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]]\n",
      "Evaluated data (h)\n",
      "[[0.49810097 0.49680498 0.5056654  0.5011553  0.49778357]\n",
      " [0.49810097 0.49680498 0.5056654  0.5011553  0.49778357]\n",
      " [0.49810097 0.49680498 0.5056654  0.5011553  0.49778357]]\n",
      "\n",
      "========== Step 1 ==========\n",
      "Evaluated data (x)\n",
      "[[0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]\n",
      " [0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]\n",
      " [0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]]\n",
      "Evaluated data (h)\n",
      "[[0.49810097 0.49680498 0.5056654  0.5011553  0.49778357]\n",
      " [0.49810097 0.49680498 0.5056654  0.5011553  0.49778357]\n",
      " [0.48235962 0.49391517 0.51611793 0.4991511  0.49216032]]\n",
      "\n",
      "========== Step 2 ==========\n",
      "Evaluated data (x)\n",
      "[[0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]\n",
      " [0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]\n",
      " [0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]]\n",
      "Evaluated data (h)\n",
      "[[0.48235962 0.49391517 0.51611793 0.4991511  0.49216032]\n",
      " [0.48235962 0.49391517 0.51611793 0.4991511  0.49216032]\n",
      " [0.48235962 0.49391517 0.51611793 0.4991511  0.49216032]]\n",
      "\n",
      "========== Step 3 ==========\n",
      "Evaluated data (x)\n",
      "[[0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ]\n",
      " [1.  0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1]\n",
      " [1.  0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1]]\n",
      "Evaluated data (h)\n",
      "[[0.48235962 0.49391517 0.51611793 0.4991511  0.49216032]\n",
      " [0.49675846 0.47097218 0.5460677  0.51355416 0.4834658 ]\n",
      " [0.49675846 0.47097218 0.5460677  0.51355416 0.4834658 ]]\n",
      "\n",
      "========== Step 4 ==========\n",
      "Evaluated data (x)\n",
      "[[1.  0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1]\n",
      " [1.  0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1]\n",
      " [1.  0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1]]\n",
      "Evaluated data (h)\n",
      "[[0.49675846 0.47097218 0.5460677  0.51355416 0.4834658 ]\n",
      " [0.49675846 0.47097218 0.5460677  0.51355416 0.4834658 ]\n",
      " [0.49675846 0.47097218 0.5460677  0.51355416 0.4834658 ]]\n",
      "\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# Defining the graph and session\n",
    "graph = tf.Graph() # Creates a graph\n",
    "session = tf.InteractiveSession(graph=graph) # Creates a session\n",
    "\n",
    "# The filename queue\n",
    "filenames = ['test%d.txt'%i for i in range(1,4)]\n",
    "filename_queue = tf.train.string_input_producer(filenames, capacity=3, shuffle=True,name='string_input_producer')\n",
    "\n",
    "# check if all files are there\n",
    "for f in filenames:\n",
    "    if not tf.gfile.Exists(f):\n",
    "        raise ValueError('Failed to find file: ' + f)\n",
    "    else:\n",
    "        print('File %s found.'%f)\n",
    "\n",
    "# Reader which takes a filename queue and \n",
    "# read() which outputs data one by one\n",
    "reader = tf.TextLineReader()\n",
    "\n",
    "# ready the data of the file and output as key,value pairs \n",
    "# We're discarding the key\n",
    "key, value = reader.read(filename_queue, name='text_read_op')\n",
    "\n",
    "# if any problems encountered with reading file \n",
    "# this is the value returned\n",
    "record_defaults = [[-1.0], [-1.0], [-1.0], [-1.0], [-1.0], [-1.0], [-1.0], [-1.0], [-1.0], [-1.0]]\n",
    "\n",
    "# decoding the read value to columns\n",
    "col1, col2, col3, col4, col5, col6, col7, col8, col9, col10 = tf.decode_csv(value, record_defaults=record_defaults)\n",
    "features = tf.stack([col1, col2, col3, col4, col5, col6, col7, col8, col9, col10])\n",
    "\n",
    "# output x is randomly assigned a batch of data of batch_size \n",
    "# where the data is read from the txt files\n",
    "x = tf.train.shuffle_batch([features], batch_size=3,\n",
    "                           capacity=5, name='data_batch', \n",
    "                           min_after_dequeue=1,num_threads=1)\n",
    "\n",
    "# QueueRunner retrieve data from queues and we need to explicitly start them\n",
    "# Coordinator coordinates multiple QueueRunners\n",
    "coord = tf.train.Coordinator()\n",
    "threads = tf.train.start_queue_runners(coord=coord, sess=session)\n",
    "\n",
    "# Building the graph by defining the variables and calculations\n",
    "\n",
    "W = tf.Variable(tf.random_uniform(shape=[10,5], minval=-0.1, maxval=0.1, dtype=tf.float32),name='W') # Variable\n",
    "b = tf.Variable(tf.zeros(shape=[5],dtype=tf.float32),name='b') # Variable\n",
    "\n",
    "h = tf.nn.sigmoid(tf.matmul(x,W) + b) # Operation to be performed\n",
    "\n",
    "# Executing operations and evaluating nodes in the graph\n",
    "tf.global_variables_initializer().run() # Initialize the variables\n",
    "\n",
    "# Calculate h with x and print the results for 5 steps\n",
    "for step in range(5):\n",
    "    x_eval, h_eval = session.run([x,h]) \n",
    "    print('========== Step %d =========='%step)\n",
    "    print('Evaluated data (x)')\n",
    "    print(x_eval)\n",
    "    print('Evaluated data (h)')\n",
    "    print(h_eval)\n",
    "    print('')\n",
    "\n",
    "# We also need to explicitly stop the coordinator \n",
    "# otherwise the process will hang indefinitely\n",
    "coord.request_stop()\n",
    "coord.join(threads)\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comparison Operators\n",
    "\n",
    "Here we discuss some operators that allows us to compare two tensors element-wise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Is X == Y (element-wise)?\n",
      "[[False False]\n",
      " [ True False]]\n",
      "\n",
      "Is X < Y (element-wise)?\n",
      "[[ True  True]\n",
      " [False False]]\n",
      "\n",
      "Is X >= Y (element-wise)?\n",
      "[[False False]\n",
      " [ True  True]]\n",
      "\n",
      "X or Y depending on the condition (element-wise)\n",
      "[[1 3]\n",
      " [3 2]]\n"
     ]
    }
   ],
   "source": [
    "# Defining the graph and session\n",
    "graph = tf.Graph() # Creates a graph\n",
    "session = tf.InteractiveSession(graph=graph) # Creates a session\n",
    "\n",
    "# Let's assume the following values for x and y\n",
    "# x (2-D tensor) => [[1,2],[3,4]]\n",
    "# y (2-D tensor) => [[4,3],[3,2]]\n",
    "x = tf.constant([[1,2],[3,4]], dtype=tf.int32)\n",
    "y = tf.constant([[4,3],[3,2]], dtype=tf.int32)\n",
    "\n",
    "# Checks if two tensors are equal element-wise and returns a boolean tensor\n",
    "# x_equal_y => [[False,False],[True,False]]\n",
    "x_equal_y = tf.equal(x, y, name=None) \n",
    "\n",
    "# Checks if x is less than y element-wise and returns a boolean tensor\n",
    "# x_less_y => [[True,True],[True,False]]\n",
    "x_less_y = tf.less(x, y, name=None) \n",
    "\n",
    "# Checks if x is greater or equal than y element-wise and returns a boolean tensor\n",
    "# x_great_equal_y => [[False,False],[True,True]]\n",
    "x_great_equal_y = tf.greater_equal(x, y, name=None) \n",
    "\n",
    "# Selects elements from x and y depending on whether,\n",
    "# the condition is satisfied (select elements from x)\n",
    "# or the condition failed (select elements from y)\n",
    "condition = tf.constant([[True,False],[True,False]],dtype=tf.bool)\n",
    "# x_cond_y => [[1,3],[3,2]]\n",
    "x_cond_y = tf.where(condition, x, y, name=None) \n",
    "\n",
    "print('Is X == Y (element-wise)?')\n",
    "print(session.run(x_equal_y))\n",
    "\n",
    "print('\\nIs X < Y (element-wise)?')\n",
    "print(session.run(x_less_y))\n",
    "\n",
    "print('\\nIs X >= Y (element-wise)?')\n",
    "print(session.run(x_great_equal_y))\n",
    "\n",
    "print('\\nX or Y depending on the condition (element-wise)')\n",
    "print(session.run(x_cond_y))\n",
    "\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Mathematical Operations\n",
    "Here we perform several mathematical opeartions you are often comfortable with"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X + Y\n",
      "[[5. 5.]\n",
      " [6. 6.]]\n",
      "\n",
      " XY\n",
      "[[10.  7.]\n",
      " [24. 17.]]\n",
      "\n",
      " log(x)\n",
      "[[0.        0.6931472]\n",
      " [1.0986123 1.3862944]]\n",
      "\n",
      " X sum over axis 1\n",
      "[3. 7.]\n",
      "\n",
      " X sum over axis 0\n",
      "[[4. 6.]]\n",
      "\n",
      " Segemented sum of a vector\n",
      "[ 6.  9. 40.]\n"
     ]
    }
   ],
   "source": [
    "# Defining the graph and session\n",
    "graph = tf.Graph() # Creates a graph\n",
    "session = tf.InteractiveSession(graph=graph) # Creates a session\n",
    "\n",
    "# Let's assume the following values for x and y\n",
    "# x (2-D tensor) => [[1,2],[3,4]]\n",
    "# y (2-D tensor) => [[4,3],[3,2]]\n",
    "x = tf.constant([[1,2],[3,4]], dtype=tf.float32)\n",
    "y = tf.constant([[4,3],[3,2]], dtype=tf.float32)\n",
    "\n",
    "# Add two tensors x and y in an element-wise fashion\n",
    "# x_add_y => [[5,5],[6,6]]\n",
    "x_add_y = tf.add(x, y) \n",
    "\n",
    "# Performs matrix multiplication (not element-wise)\n",
    "# x_mul_y => [[10,7],[24,17]]\n",
    "x_mul_y = tf.matmul(x, y) \n",
    "\n",
    "# Compute natural logarithm of x element-wise\n",
    "# equivalent to computing ln(x)\n",
    "# log_x => [[0,0.6931],[1.0986,1.3863]]\n",
    "log_x = tf.log(x) \n",
    "\n",
    "# Performs reduction operation across the specified axis\n",
    "# x_sum_1 => [3,7]\n",
    "x_sum_1 = tf.reduce_sum(x, axis=[1], keepdims=False)\n",
    "\n",
    "# x_sum_2 => [[4],[6]]\n",
    "x_sum_2 = tf.reduce_sum(x, axis=[0], keepdims=True) \n",
    "\n",
    "# Segments the tensor according to segment_ids (items with same id in\n",
    "# the same segment) and computes a segmented sum of the data\n",
    "\n",
    "data = tf.constant([1,2,3,4,5,6,7,8,9,10], dtype=tf.float32)\n",
    "segment_ids = tf.constant([0,0,0,1,1,2,2,2,2,2 ], dtype=tf.int32)\n",
    "# x_seg_sum => [6,9,40]\n",
    "x_seg_sum = tf.segment_sum(data, segment_ids) \n",
    "\n",
    "print('X + Y')\n",
    "print(session.run(x_add_y))\n",
    "print('\\n XY')\n",
    "print(session.run(x_mul_y))\n",
    "print('\\n log(x)')\n",
    "print(session.run(log_x))\n",
    "print('\\n X sum over axis 1')\n",
    "print(session.run(x_sum_1))\n",
    "print('\\n X sum over axis 0')\n",
    "print(session.run(x_sum_2))\n",
    "print('\\n Segemented sum of a vector')\n",
    "print(session.run(x_seg_sum))\n",
    "\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Scatter and Gather Operations\n",
    "\n",
    "Scatter operation can distributed a set of values to specific positions of a tensor, where the gather operation can obtain a slice of a tensor specified by a set of indices."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Scatter Update Operation for 1-D\n",
      "[1. 2. 3. 4. 5.]\n",
      "\n",
      "Scatter Operation for n-D\n",
      "[[0 0 0]\n",
      " [1 1 1]\n",
      " [0 0 0]\n",
      " [2 2 2]]\n",
      "\n",
      "Scatter Operation for n-D\n",
      "[[0 0 0]\n",
      " [1 0 0]\n",
      " [0 0 0]\n",
      " [0 2 0]]\n",
      "\n",
      "Gather Operation for 1-D\n",
      "[2. 5.]\n",
      "\n",
      "Gather Operation for n-D\n",
      "[[0. 0. 0.]\n",
      " [2. 2. 2.]]\n",
      "\n",
      "Gather Operation for n-D\n",
      "[0. 2.]\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# Defining the graph and session\n",
    "graph = tf.Graph() # Creates a graph\n",
    "session = tf.InteractiveSession(graph=graph) # Creates a session\n",
    "\n",
    "# 1-D scatter operation\n",
    "ref = tf.Variable(tf.constant([1,9,3,10,5],dtype=tf.float32),name='scatter_update')\n",
    "indices = [1,3]\n",
    "updates = tf.constant([2,4],dtype=tf.float32)\n",
    "tf_scatter_update = tf.scatter_update(ref, indices, updates, use_locking=None, name=None) \n",
    "\n",
    "tf.global_variables_initializer().run() # Initialize the variables\n",
    "print('\\nScatter Update Operation for 1-D')\n",
    "print(session.run(tf_scatter_update))\n",
    "\n",
    "# n-D scatter operation\n",
    "indices = [[1],[3]]\n",
    "updates = tf.constant([[1,1,1],[2,2,2]])\n",
    "shape = [4,3]\n",
    "tf_scatter_nd_1 = tf.scatter_nd(indices, updates, shape, name=None)\n",
    "print('\\nScatter Operation for n-D')\n",
    "print(session.run(tf_scatter_nd_1))\n",
    "\n",
    "# n-D scatter operation\n",
    "indices = [[1,0],[3,1]] # 2 x 2\n",
    "updates = tf.constant([1,2]) # 2 x 1\n",
    "shape = [4,3] # 2\n",
    "tf_scatter_nd_2 = tf.scatter_nd(indices, updates, shape, name=None)\n",
    "\n",
    "print('\\nScatter Operation for n-D')\n",
    "print(session.run(tf_scatter_nd_2))\n",
    "\n",
    "# 1-D gather operation\n",
    "params = tf.constant([1,2,3,4,5],dtype=tf.float32)\n",
    "indices = [1,4]\n",
    "tf_gather = tf.gather(params, indices, validate_indices=True, name=None) #=> [2,5]\n",
    "print('\\nGather Operation for 1-D')\n",
    "print(session.run(tf_gather))\n",
    "\n",
    "# n-D gather operation\n",
    "params = tf.constant([[0,0,0],[1,1,1],[2,2,2],[3,3,3]],dtype=tf.float32)\n",
    "indices = [[0],[2]]\n",
    "tf_gather_nd = tf.gather_nd(params, indices, name=None) #=> [[0,0,0],[2,2,2]]\n",
    "print('\\nGather Operation for n-D')\n",
    "print(session.run(tf_gather_nd))\n",
    "\n",
    "params = tf.constant([[0,0,0],[1,1,1],[2,2,2],[3,3,3]],dtype=tf.float32)\n",
    "indices = [[0,1],[2,2]]\n",
    "tf_gather_nd_2 = tf.gather_nd(params, indices, name=None) #=> [[0,0,0],[2,2,2]]\n",
    "print('\\nGather Operation for n-D')\n",
    "print(session.run(tf_gather_nd_2))\n",
    "\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2-Dimensional Operations (2D Convolution and 2D Max pooling)\n",
    "2D Convolution and Max pooling are two operation you perform on a tensor over the width and height axes. These operations are often used in convolution neural networks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "2-D Convolution operation\n",
      "[[[[ 7.5]\n",
      "   [ 7.5]\n",
      "   [ 7.5]]\n",
      "\n",
      "  [[13.5]\n",
      "   [13.5]\n",
      "   [13.5]]\n",
      "\n",
      "  [[19.5]\n",
      "   [19.5]\n",
      "   [19.5]]]]\n",
      "\n",
      "Max pooling operation\n",
      "[[[[4.]\n",
      "   [4.]]\n",
      "\n",
      "  [[8.]\n",
      "   [8.]]]]\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# Defining the graph and session\n",
    "graph = tf.Graph() # Creates a graph\n",
    "session = tf.InteractiveSession(graph=graph) # Creates a session\n",
    "\n",
    "x = tf.constant(\n",
    "    [[\n",
    "        [[1],[2],[3],[4]],\n",
    "        [[4],[3],[2],[1]],\n",
    "        [[5],[6],[7],[8]],\n",
    "        [[8],[7],[6],[5]]\n",
    "    ]],\n",
    "    dtype=tf.float32)\n",
    "\n",
    "x_filter = tf.constant(\n",
    "    [\n",
    "        [\n",
    "            [[0.5]],[[1]]\n",
    "        ],\n",
    "        [\n",
    "            [[0.5]],[[1]]\n",
    "        ]\n",
    "    ],\n",
    "    dtype=tf.float32)\n",
    "\n",
    "x_stride = [1,1,1,1]\n",
    "x_padding = 'VALID'\n",
    "\n",
    "x_conv = tf.nn.conv2d(\n",
    "    input=x, filter=x_filter,\n",
    "    strides=x_stride, padding=x_padding\n",
    ")\n",
    "\n",
    "print('\\n2-D Convolution operation')\n",
    "print(session.run(x_conv))\n",
    "\n",
    "x = tf.constant(\n",
    "    [[\n",
    "        [[1],[2],[3],[4]],\n",
    "        [[4],[3],[2],[1]],\n",
    "        [[5],[6],[7],[8]],\n",
    "        [[8],[7],[6],[5]]\n",
    "    ]],\n",
    "    dtype=tf.float32)\n",
    "\n",
    "x_ksize = [1,2,2,1]\n",
    "x_stride = [1,2,2,1]\n",
    "x_padding = 'VALID'\n",
    "\n",
    "x_pool = tf.nn.max_pool(\n",
    "    value=x, ksize=x_ksize,\n",
    "    strides=x_stride, padding=x_padding\n",
    ")\n",
    "\n",
    "print('\\nMax pooling operation')\n",
    "print(session.run(x_pool))\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Loss Functions\n",
    "Here we define several well-known loss functions that are commonly used in optimizing neural networks.\n",
    "1. Mean Squared Error (MSE)\n",
    " * $MSE = (1/N)\\sum_{i=1}^{N} {(x_i-\\hat{x}_i)}^2$\n",
    " \n",
    "2. Cross Entropy Loss (CE)\n",
    " * $CE = -(1/N)\\sum_{i=1}^{N}y_ilog(\\hat{y}_i) + (1-y_i)log(1-\\hat{y}_i)$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MSE Loss:  15.0\n",
      "CE Loss:  0.08775769\n"
     ]
    }
   ],
   "source": [
    "# Defining the graph and session\n",
    "graph = tf.Graph() # Creates a graph\n",
    "session = tf.InteractiveSession(graph=graph) # Creates a session\n",
    "\n",
    "# Returns half of L2 norm of t given by sum(t**2)/2\n",
    "x = tf.constant([[2,4],[6,8]],dtype=tf.float32)\n",
    "x_hat = tf.constant([[1,2],[3,4]],dtype=tf.float32)\n",
    "# MSE = (1**2 + 2**2 + 3**2 + 4**2)/2 = 15\n",
    "MSE = tf.nn.l2_loss(x-x_hat)\n",
    "\n",
    "# A common loss function used in neural networks to optimize the network\n",
    "# Calculating the cross_entropy with logits (unnormalized outputs of the last layer)\n",
    "# instead of outputs leads to better numerical stabilities\n",
    "\n",
    "y = tf.constant([[1,0],[0,1]],dtype=tf.float32)\n",
    "y_hat = tf.constant([[3,1],[2,5]],dtype=tf.float32)\n",
    "# This function alone doesnt average the cross entropy losses of all data points,\n",
    "# You need to do that manually using reduce_mean function\n",
    "CE = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=y_hat,labels=y))\n",
    "\n",
    "print('MSE Loss: ',session.run(MSE))\n",
    "print('CE Loss: ',session.run(CE))\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Stochastic Optimization\n",
    "Here we discuss how to implement optimization with TensorFlow. The objective of this example is to find the mininum point of a given function. For this example, we will use a simple quadratic function where $y = x^2$. We will start at an arbitrary point (say $x=2$) and keep minimizing $y$ until we reach the minimum $y$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Step:  0 , x:  2.0 , y:  4.0\n",
      "Step:  1 , x:  1.6 , y:  2.5600002\n",
      "Step:  2 , x:  1.28 , y:  1.6384\n",
      "Step:  3 , x:  1.0239999 , y:  1.0485759\n",
      "Step:  4 , x:  0.8191999 , y:  0.6710885\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n+vXrM2PGDN566y369evHkCFDOPzwwzO07ooVK2jZsiX58uXjrLPOYsOGDXzwwQdceuml5MqVi4sv\nvhiA0047DYDXX3+dNm3a7PChgLTfiTHmiF+HHXZYlJT9bNycEl8dNTc27jEo1rjj4/iPD6fEX9ds\nSHYsSZIkScpxJk6cGPPmzRtDCPHCCy+Mffr0ifPnz9/lc1577bUIxNdeey3d+0uWLImrVq3a4fq3\n334bCxcuHE8++eQ/XJ83b14EIhDvvPPOdOds06ZNTJSk0letWrVYrVq1dHPmzp07Dhky5A/37rjj\njgjEluddH6vd/nE8/P7Bsff4H+Kxxx4bgfj888//YfzAgQO3ZtzZ695e9+7dIxDz5s0bJ06c+Id7\nN954YwTipZdeuvVaampqrFu3bgTiW2+99Yfx7777bgRinTp1YkpKyg5rDBs27A/jt2S97LLL4ubN\nm7denzp1asydO3esV6/eH8YPGzYsArF79+4Zem1SMgDjYwZqvrYNkbRX5c2di0ta1mD4LW258Khq\nvP31Qto+OoxXR81jU0pqsuNJkiRJUo7RrFkz3nrrLcqVK8dbb73FmWeeSfXq1SlVqhSnn346H330\nUabnLFu2LEWL7vgN2iZNmnDssccybNgwNm3atMP9cuXK/WFndVY599xzOe6447b+vG5jCnnrnwDA\npG8mcE27Qxh2S1uOKBsZOnQoNWvW5Morr/zDHO3bt+f444/frfW7du1Ks2bN/nCtR48eFCtWjLff\nfpsNGzYAiRYuM2bMoEWLFlxwwQV/GN+lSxdatWrFzJkzGTVqVIbWLVSoEE888QS5c/9/v+769evT\nsmVLpk+fzpo1a3br9UjZncVrSftEicL5uLdzQz65oTVNqhTn3o+ncZL9sCVJkiQpS51zzjksXLiQ\nQYMGcffdd3PqqaeSmppK37596dSpExdffHGm/xtswIABdOzYkQoVKpA3b96tPZQ/+ugjNmzYwLJl\ny3Z4TpMmTcifP39WvaytmjdvDvx/X+tjHx/O61MShdvGZfJw60l1KZw/D99++y0ALVq0IFeuHctf\nrVq12q3127Rps8O1YsWK0bRpU9avX7+19/bEiRMBOPbYY9OdZ8v1b775JkPr1qpVi4MOOmiH61Wq\nVAHgt99+y9A80v7GnteS9qna5YryxqVHMHTGLzw4cDpXvDmBI2qU5O8d6tGkSvFkx5MkSZKk/V7e\n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\ncXastO9NioiIVClffPEFBQUF3H777TRt2vSixz344INMmjSJAwcOsGrVqmLd13PnzmXhwoUMHTqU\n7t27s2PHDubMmcOKFStYv349UVFRALz44ovMmzePnTt38tRTT+Hr6wtQ+OvlbN68mTfeeINu3box\nbtw4du/ezdy5c9mzZw/z58+nc+fONGjQgHvvvZfo6Gjmzp1Lnz59OHr0KJ6enpe89vjx40lNTS22\n/eeff2bbtm24u/850mzu3Ll8/PHH9OjRg44dO+Li4sLevXuZPn06P//8M1u2bCkcSTJkyBAAZs6c\nSbdu3ejevXvhdS43S3jBggUMHz4cwzAYMWIE4eHhbN26lY8++oj58+ezdu1aateuXey85557jsWL\nFzNw4ED69u3LihUrmDZtGocPH2b58uWXvOeF3nnnHZYsWcKoUaPo378/a9eu5YsvvmDlypVs3LiR\nv67PNG3aNH788Ue6detG7969sdvtbN26lbfffpuFCxeyceNGvLy8ADNo9/X1Zf78+QwePJgWLVoU\nXufC/x4+/PBDfvrpJwYNGkS3bt3YuHEj3377LTt37mTHjh24urpe0WO6meTl5fHcc8/x6aefltht\nbbVaCQ4O5ueff6ZRo0bXdK+cfBtztsUyfc0xjiVnUsvPnUmDGzOydRhWF8druraIyA3LMIwb4qt1\n69aGiMjNKCe/wPh28wmj979XGuH/u8Do8OpSY9rqI0Z6Tn5FlyYiIlLl9ezZ0wCMTz/99LLH3nnn\nnQZgTJ48uXDbF198YQAGYPz8889Fjp86daoBGD179iyy/b777jMA49ixYyXep1u3bob5Uu5PK1as\nKLzPf//73yL7xo4dawBGtWrVjFdeeaXIvkmTJhmAMXXq1Cuq4bwlS5YYTk5ORr169YxTp04Vbo+N\njTVycnKKHb948WLDwcHBePjhh0us/8UXXyzxPuefxy+++KJwW3p6uuHn52c4ODgYq1evLnL866+/\nbgBGnz59SnxcYWFhRnR0dOH2/Px8o0uXLgZgbNy48ZKP+bwXX3zRAAxnZ2dj27ZtRfaNHz/eAIyx\nY8cW2X78+HGjoKCg2LWmT59uAMbrr79+2cddUg1eXl7Grl27iuwbPXq0ARjffvttqR7PzejQoUNG\nw4YNDXd398L/f/765e7ubjz44INGdnb2Nd0nJSPXeHfpQaPVpCVG+P8uMAa9v8ZYsDPeKLDZy+iR\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x2689270cfd0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "graph = tf.get_default_graph() # You can also get the TensorFlow's default graph instead of creating a new graph object\n",
    "session = tf.InteractiveSession(graph=graph) # Creates a session if you don't specify a graph the new graph will be passed\n",
    "\n",
    "# Optimizers play the role of tuning neural network parameters so that their task error is minimal\n",
    "# For example task error can be the cross_entropy error for a classification task\n",
    "tf_x = tf.Variable(tf.constant(2.0,dtype=tf.float32),name='x') \n",
    "tf_y = tf_x**2\n",
    "minimize_op = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(tf_y)\n",
    "\n",
    "x_series, y_series = [],[]\n",
    "tf.global_variables_initializer().run()\n",
    "for step in range(5):\n",
    "    _, x,y = session.run([minimize_op,tf_x,tf_y])\n",
    "    print('Step: ',step, ', x: ',x, ', y: ',y)\n",
    "    x_series.append(x)\n",
    "    y_series.append(y)\n",
    "\n",
    "\n",
    "\n",
    "fig, ax = plt.subplots(nrows=1, ncols=1)\n",
    "fig.set_size_inches(w=25,h=5)\n",
    "ax.plot(np.arange(-4,4.1,0.1),np.arange(-4,4.1,0.1)**2)\n",
    "ax.scatter(x_series,y_series,c='red',linewidths=4)\n",
    "\n",
    "x_offset, y_offset = 0.02, 0.75\n",
    "ax.annotate('Starting point', xy=(2.01, 4.1), xytext=(2.5, 8),\n",
    "            arrowprops=dict(facecolor='black', shrink=0.01),fontsize=20\n",
    "            )\n",
    "\n",
    "ax.annotate('Optimization path', xy=(2.01, 4.1), xytext=(0.6, 5),\n",
    "            arrowprops=None,fontsize=20\n",
    "            )\n",
    "\n",
    "\n",
    "for index,(x,y) in enumerate(zip(x_series,y_series)):\n",
    "    if index == len(x_series)-1:\n",
    "        break\n",
    "    ax.annotate('', xy=(x_series[index+1], y_series[index+1]+y_offset), xytext=( x - x_offset, y + y_offset),\n",
    "                arrowprops=dict(facecolor='red', edgecolor='red', shrink=0.01),fontsize=20\n",
    "                )\n",
    "\n",
    "ax.set_xlabel('x',fontsize=20)\n",
    "ax.set_ylabel('y',fontsize=20)\n",
    "ax.set_title('Optimizing y=x^2',fontsize=22)\n",
    "fig.savefig('optimization.jpg')\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using tf.control_dependencies(...) Operation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "z= 4.0\n",
      "x= 2.0\n"
     ]
    }
   ],
   "source": [
    "# if you don't pass a graph, the default_graph will be used by TensorFlow as the graph\n",
    "session = tf.InteractiveSession()\n",
    "\n",
    "x = tf.Variable(tf.constant(2.0), name='x')\n",
    "x_assign_op = tf.assign(x, x+5)\n",
    "z = x*2\n",
    "\n",
    "tf.global_variables_initializer().run()\n",
    "\n",
    "print('z=',session.run(z))\n",
    "print('x=',session.run(x))\n",
    "\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "z= 14.0\n",
      "x= 7.0\n"
     ]
    }
   ],
   "source": [
    "session = tf.InteractiveSession()\n",
    "x = tf.Variable(tf.constant(2.0), name='x')\n",
    "with tf.control_dependencies([tf.assign(x, x+5)]):\n",
    "  z = x*2\n",
    "\n",
    "tf.global_variables_initializer().run()\n",
    "\n",
    "print('z=',session.run(z))\n",
    "print('x=',session.run(x))\n",
    "\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Variable Scoping\n",
    "\n",
    "Here we will see how we can use variable scoping to reuse variables during the execution of the code. First we will see that TensorFlow creates variables everytime we execute code if scoping is not used. Then we look at how to solve this issue with scoping."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "14.0\n",
      "['x:0', 'y:0', 'x_1:0', 'y_1:0', 'x_2:0', 'y_2:0', 'x_3:0', 'y_3:0', 'x_4:0', 'y_4:0', 'x_5:0', 'y_5:0', 'x_6:0', 'y_6:0', 'x_7:0', 'y_7:0', 'x_8:0', 'y_8:0', 'x_9:0', 'y_9:0', 'x_10:0', 'y_10:0']\n"
     ]
    }
   ],
   "source": [
    "tf.reset_default_graph()\n",
    "# Defining the graph and session\n",
    "session = tf.InteractiveSession() # Creates a session with default graph\n",
    "\n",
    "def very_simple_computation(w):\n",
    "  x = tf.Variable(tf.constant(5.0, shape=None, dtype=tf.float32), name='x')\n",
    "  y = tf.Variable(tf.constant(2.0, shape=None, dtype=tf.float32), name='y')\n",
    "  z = x*w + y**2\n",
    "  return z\n",
    "\n",
    "z1 = very_simple_computation(2)\n",
    "\n",
    "for _ in range(10):\n",
    "    z1 = very_simple_computation(2)\n",
    "    \n",
    "tf.global_variables_initializer().run()\n",
    "print(session.run(z1))\n",
    "\n",
    "print([v.name for v in tf.global_variables()])\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[9.0, 90.0, 9.0, 90.0, 9.0, 90.0]\n",
      "['x:0', 'x_1:0', 'x_2:0', 'scopeA/x:0', 'scopeA/y:0', 'scopeB/x:0', 'scopeB/y:0']\n"
     ]
    }
   ],
   "source": [
    "tf.reset_default_graph()\n",
    "# Defining the graph and session\n",
    "session = tf.InteractiveSession(graph=graph) # Creates a session\n",
    "\n",
    "\n",
    "def not_so_simple_computation(w):\n",
    "  x = tf.get_variable('x', initializer=tf.constant (5.0, shape=None, dtype=tf.float32))\n",
    "  y = tf.get_variable('y', initializer=tf.constant(2.0, shape=None, dtype=tf.float32)) \n",
    "  z = x*w + y**2\n",
    "  return z\n",
    "\n",
    "def another_not_so_simple_computation(w):\n",
    "  x = tf.get_variable('x', initializer=tf.constant(5.0, shape=None, dtype=tf.float32))\n",
    "  y = tf.get_variable('y', initializer=tf.constant(2.0, shape=None, dtype=tf.float32)) \n",
    "  z = w*x*y\n",
    "  return z\n",
    " \n",
    "# Since this is the first call, the variables will be created with following names\n",
    "# x => scopeA/x, y => scopeA/y\n",
    "with tf.variable_scope('scopeA'):\n",
    "  z1 = not_so_simple_computation(tf.constant(1.0,dtype=tf.float32))\n",
    "# scopeA/x and scopeA/y alread created we reuse them\n",
    "with tf.variable_scope('scopeA',reuse=True):\n",
    "  z2 = another_not_so_simple_computation(z1)\n",
    "\n",
    "# Since this is the first call, the variables will be created with following names\n",
    "# x => scopeB/x, y => scopeB/y\n",
    "with tf.variable_scope('scopeB'):\n",
    "  a1 = not_so_simple_computation(tf.constant(1.0,dtype=tf.float32))\n",
    "# scopeB/x and scopeB/y alread created we reuse them\n",
    "with tf.variable_scope('scopeB',reuse=True):\n",
    "  a2 = another_not_so_simple_computation(a1)\n",
    "\n",
    "# Say we want to reuse the \"scopeA\" scope again, since variables are already created\n",
    "# we should set \"reuse\" argument to True when invoking the scope\n",
    "with tf.variable_scope('scopeA',reuse=True):\n",
    "  zz1 = not_so_simple_computation(tf.constant(1.0,dtype=tf.float32))\n",
    "  zz2 = another_not_so_simple_computation(z1)\n",
    "\n",
    "tf.global_variables_initializer().run()\n",
    "print(session.run([z1,z2,a1,a2,zz1,zz2]))\n",
    "print([v.name for v in tf.global_variables()])\n",
    "\n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# MNIST Classification"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Download and Prepare Data\n",
    "\n",
    "The code below downloads the MNIST data set from source, reshapes the images to [number_of_training_samples, single_image_size] matrix and standardize (make zero-mean unit-variance) images. Then we do the same for testing images as well."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found and verified train-images-idx3-ubyte.gz\n",
      "Found and verified train-labels-idx1-ubyte.gz\n",
      "Found and verified t10k-images-idx3-ubyte.gz\n",
      "Found and verified t10k-labels-idx1-ubyte.gz\n",
      "\n",
      "Reading files train-images-idx3-ubyte.gz and train-labels-idx1-ubyte.gz\n",
      "60000 28 28\n",
      "(Images) Returned a tensor of shape  (60000, 784)\n",
      "(Labels) Returned a tensor of shape: 60000\n",
      "Sample labels:  [5 0 4 1 9 2 1 3 1 4]\n",
      "\n",
      "Reading files t10k-images-idx3-ubyte.gz and t10k-labels-idx1-ubyte.gz\n",
      "10000 28 28\n",
      "(Images) Returned a tensor of shape  (10000, 784)\n",
      "(Labels) Returned a tensor of shape: 10000\n",
      "Sample labels:  [7 2 1 0 4 1 4 9 5 9]\n"
     ]
    }
   ],
   "source": [
    "import struct\n",
    "import gzip\n",
    "import os\n",
    "from six.moves.urllib.request import urlretrieve\n",
    "\n",
    "def maybe_download(url, filename, expected_bytes, force=False):\n",
    "  \"\"\"Download a file if not present, and make sure it's the right size.\"\"\"\n",
    "  if force or not os.path.exists(filename):\n",
    "    print('Attempting to download:', filename) \n",
    "    filename, _ = urlretrieve(url + filename, filename)\n",
    "    print('\\nDownload Complete!')\n",
    "  statinfo = os.stat(filename)\n",
    "  if statinfo.st_size == expected_bytes:\n",
    "    print('Found and verified', filename)\n",
    "  else:\n",
    "    raise Exception(\n",
    "      'Failed to verify ' + filename + '. Can you get to it with a browser?')\n",
    "  return filename\n",
    "\n",
    "\n",
    "def read_mnist(fname_img, fname_lbl):\n",
    "    print('\\nReading files %s and %s'%(fname_img, fname_lbl))\n",
    "    \n",
    "    with gzip.open(fname_img) as fimg:        \n",
    "        magic, num, rows, cols = struct.unpack(\">IIII\", fimg.read(16))\n",
    "        print(num,rows,cols)\n",
    "        img = (np.frombuffer(fimg.read(num*rows*cols), dtype=np.uint8).reshape(num, rows * cols)).astype(np.float32)\n",
    "        print('(Images) Returned a tensor of shape ',img.shape)\n",
    "        \n",
    "        img = (img - np.mean(img))/np.std(img)\n",
    "        \n",
    "    with gzip.open(fname_lbl) as flbl:\n",
    "        # flbl.read(8) reads upto 8 bytes\n",
    "        magic, num = struct.unpack(\">II\", flbl.read(8))        \n",
    "        lbl = np.frombuffer(flbl.read(num), dtype=np.int8)\n",
    "        print('(Labels) Returned a tensor of shape: %s'%lbl.shape)\n",
    "        print('Sample labels: ',lbl[:10])\n",
    "        \n",
    "    return img, lbl\n",
    "    \n",
    "    \n",
    "# Download data if needed\n",
    "url = 'http://yann.lecun.com/exdb/mnist/'\n",
    "# training data\n",
    "maybe_download(url,'train-images-idx3-ubyte.gz',9912422)\n",
    "maybe_download(url,'train-labels-idx1-ubyte.gz',28881)\n",
    "# testing data\n",
    "maybe_download(url,'t10k-images-idx3-ubyte.gz',1648877)\n",
    "maybe_download(url,'t10k-labels-idx1-ubyte.gz',4542)\n",
    "\n",
    "# Read the training and testing data \n",
    "train_inputs, train_labels = read_mnist('train-images-idx3-ubyte.gz', 'train-labels-idx1-ubyte.gz')\n",
    "test_inputs, test_labels = read_mnist('t10k-images-idx3-ubyte.gz', 't10k-labels-idx1-ubyte.gz')\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Defining Hyperparameters and Some Constants"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "WEIGHTS_STRING = 'weights'\n",
    "BIAS_STRING = 'bias'\n",
    "\n",
    "batch_size = 100\n",
    "\n",
    "img_width, img_height = 28,28\n",
    "input_size = img_height * img_width\n",
    "num_labels = 10\n",
    "\n",
    "# resets the default graph Otherwise raises an error about already initialized variables\n",
    "tf.reset_default_graph()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Defining Input and Label Placeholders"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Defining inputs and outputs\n",
    "tf_inputs = tf.placeholder(shape=[batch_size, input_size], dtype=tf.float32, name = 'inputs')\n",
    "tf_labels = tf.placeholder(shape=[batch_size, num_labels], dtype=tf.float32, name = 'labels')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Defining the Weights and Bias Variables (with Scoping)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Defining the Tensorflow variables\n",
    "def define_net_parameters():\n",
    "    with tf.variable_scope('layer1'):\n",
    "        tf.get_variable(WEIGHTS_STRING,shape=[input_size,500],\n",
    "                            initializer=tf.random_normal_initializer(0,0.02))\n",
    "        tf.get_variable(BIAS_STRING, shape=[500],\n",
    "                           initializer=tf.random_uniform_initializer(0,0.01))\n",
    "        \n",
    "    with tf.variable_scope('layer2'):\n",
    "        tf.get_variable(WEIGHTS_STRING,shape=[500,250],\n",
    "                            initializer=tf.random_normal_initializer(0,0.02))\n",
    "        tf.get_variable(BIAS_STRING, shape=[250],\n",
    "                           initializer=tf.random_uniform_initializer(0,0.01))\n",
    "    \n",
    "    with tf.variable_scope('output'):\n",
    "        tf.get_variable(WEIGHTS_STRING,shape=[250,10],\n",
    "                            initializer=tf.random_normal_initializer(0,0.02))\n",
    "        tf.get_variable(BIAS_STRING, shape=[10],\n",
    "                           initializer=tf.random_uniform_initializer(0,0.01))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Defining the Inference Operation\n",
    "\n",
    "Here we calculate the output logits (unnormalized scores) for a given input x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Defining calcutations in the neural network starting from inputs to logits\n",
    "# logits are the values before applying softmax to the final output\n",
    "        \n",
    "def inference(x):\n",
    "    # calculations for layer 1\n",
    "    with tf.variable_scope('layer1',reuse=True):\n",
    "        w,b = tf.get_variable(WEIGHTS_STRING), tf.get_variable(BIAS_STRING)\n",
    "        tf_h1 = tf.nn.relu(tf.matmul(x,w) + b, name = 'hidden1')\n",
    "\n",
    "    # calculations for layer 2\n",
    "    with tf.variable_scope('layer2',reuse=True):\n",
    "        w,b = tf.get_variable(WEIGHTS_STRING), tf.get_variable(BIAS_STRING)\n",
    "        tf_h2 = tf.nn.relu(tf.matmul(tf_h1,w) + b, name = 'hidden1')\n",
    "\n",
    "    # calculations for output layer\n",
    "    with tf.variable_scope('output',reuse=True):\n",
    "        w,b = tf.get_variable(WEIGHTS_STRING), tf.get_variable(BIAS_STRING)\n",
    "        tf_logits = tf.nn.bias_add(tf.matmul(tf_h2,w), b, name = 'logits')\n",
    "\n",
    "    return tf_logits"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Defining Loss Function and the Optimizer\n",
    "We use the cross entropy loss function and a momentum-based optimizer for learning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "define_net_parameters()\n",
    "\n",
    "# defining the loss\n",
    "tf_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=inference(tf_inputs), labels=tf_labels))\n",
    "\n",
    "# defining the optimize function\n",
    "tf_loss_minimize = tf.train.MomentumOptimizer(momentum=0.9,learning_rate=0.01).minimize(tf_loss)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Defining Predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# defining predictions\n",
    "tf_predictions = tf.nn.softmax(inference(tf_inputs))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Executing the Graph to get the Classification Results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sample labels (one-hot)\n",
      "[[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]\n",
      " [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n",
      " [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]\n",
      " [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]\n",
      " [0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]\n",
      " [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]\n",
      " [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]\n",
      " [0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]\n",
      " [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]\n",
      " [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]]\n",
      "\n",
      "Average train loss for the 1 epoch: 0.448\n",
      "\n",
      "\tAverage test accuracy for the 1 epoch: 94.34\n",
      "\n",
      "Average train loss for the 2 epoch: 0.139\n",
      "\n",
      "\tAverage test accuracy for the 2 epoch: 96.06\n",
      "\n",
      "Average train loss for the 3 epoch: 0.090\n",
      "\n",
      "\tAverage test accuracy for the 3 epoch: 97.01\n",
      "\n",
      "Average train loss for the 4 epoch: 0.064\n",
      "\n",
      "\tAverage test accuracy for the 4 epoch: 97.29\n",
      "\n",
      "Average train loss for the 5 epoch: 0.047\n",
      "\n",
      "\tAverage test accuracy for the 5 epoch: 97.52\n",
      "\n",
      "Average train loss for the 6 epoch: 0.034\n",
      "\n",
      "\tAverage test accuracy for the 6 epoch: 97.70\n",
      "\n",
      "Average train loss for the 7 epoch: 0.026\n",
      "\n",
      "\tAverage test accuracy for the 7 epoch: 97.82\n",
      "\n",
      "Average train loss for the 8 epoch: 0.019\n",
      "\n",
      "\tAverage test accuracy for the 8 epoch: 97.99\n",
      "\n",
      "Average train loss for the 9 epoch: 0.014\n",
      "\n",
      "\tAverage test accuracy for the 9 epoch: 98.02\n",
      "\n",
      "Average train loss for the 10 epoch: 0.011\n",
      "\n",
      "\tAverage test accuracy for the 10 epoch: 98.01\n",
      "\n",
      "Average train loss for the 11 epoch: 0.008\n",
      "\n",
      "\tAverage test accuracy for the 11 epoch: 98.10\n",
      "\n",
      "Average train loss for the 12 epoch: 0.006\n",
      "\n",
      "\tAverage test accuracy for the 12 epoch: 98.02\n",
      "\n",
      "Average train loss for the 13 epoch: 0.004\n",
      "\n",
      "\tAverage test accuracy for the 13 epoch: 98.12\n",
      "\n",
      "Average train loss for the 14 epoch: 0.003\n",
      "\n",
      "\tAverage test accuracy for the 14 epoch: 98.16\n",
      "\n",
      "Average train loss for the 15 epoch: 0.002\n",
      "\n",
      "\tAverage test accuracy for the 15 epoch: 98.18\n",
      "\n",
      "Average train loss for the 16 epoch: 0.002\n",
      "\n",
      "\tAverage test accuracy for the 16 epoch: 98.17\n",
      "\n",
      "Average train loss for the 17 epoch: 0.002\n",
      "\n",
      "\tAverage test accuracy for the 17 epoch: 98.18\n",
      "\n",
      "Average train loss for the 18 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 18 epoch: 98.19\n",
      "\n",
      "Average train loss for the 19 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 19 epoch: 98.18\n",
      "\n",
      "Average train loss for the 20 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 20 epoch: 98.21\n",
      "\n",
      "Average train loss for the 21 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 21 epoch: 98.23\n",
      "\n",
      "Average train loss for the 22 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 22 epoch: 98.21\n",
      "\n",
      "Average train loss for the 23 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 23 epoch: 98.21\n",
      "\n",
      "Average train loss for the 24 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 24 epoch: 98.22\n",
      "\n",
      "Average train loss for the 25 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 25 epoch: 98.19\n",
      "\n",
      "Average train loss for the 26 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 26 epoch: 98.21\n",
      "\n",
      "Average train loss for the 27 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 27 epoch: 98.21\n",
      "\n",
      "Average train loss for the 28 epoch: 0.001\n",
      "\n",
      "\tAverage test accuracy for the 28 epoch: 98.21\n",
      "\n",
      "Average train loss for the 29 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 29 epoch: 98.23\n",
      "\n",
      "Average train loss for the 30 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 30 epoch: 98.23\n",
      "\n",
      "Average train loss for the 31 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 31 epoch: 98.25\n",
      "\n",
      "Average train loss for the 32 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 32 epoch: 98.25\n",
      "\n",
      "Average train loss for the 33 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 33 epoch: 98.26\n",
      "\n",
      "Average train loss for the 34 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 34 epoch: 98.27\n",
      "\n",
      "Average train loss for the 35 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 35 epoch: 98.28\n",
      "\n",
      "Average train loss for the 36 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 36 epoch: 98.28\n",
      "\n",
      "Average train loss for the 37 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 37 epoch: 98.27\n",
      "\n",
      "Average train loss for the 38 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 38 epoch: 98.28\n",
      "\n",
      "Average train loss for the 39 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 39 epoch: 98.28\n",
      "\n",
      "Average train loss for the 40 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 40 epoch: 98.28\n",
      "\n",
      "Average train loss for the 41 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 41 epoch: 98.28\n",
      "\n",
      "Average train loss for the 42 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 42 epoch: 98.28\n",
      "\n",
      "Average train loss for the 43 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 43 epoch: 98.28\n",
      "\n",
      "Average train loss for the 44 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 44 epoch: 98.28\n",
      "\n",
      "Average train loss for the 45 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 45 epoch: 98.28\n",
      "\n",
      "Average train loss for the 46 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 46 epoch: 98.28\n",
      "\n",
      "Average train loss for the 47 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 47 epoch: 98.27\n",
      "\n",
      "Average train loss for the 48 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 48 epoch: 98.27\n",
      "\n",
      "Average train loss for the 49 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 49 epoch: 98.27\n",
      "\n",
      "Average train loss for the 50 epoch: 0.000\n",
      "\n",
      "\tAverage test accuracy for the 50 epoch: 98.27\n",
      "\n"
     ]
    }
   ],
   "source": [
    "session = tf.InteractiveSession()\n",
    "\n",
    "tf.global_variables_initializer().run()\n",
    "\n",
    "NUM_EPOCHS = 50\n",
    "\n",
    "def accuracy(predictions, labels):\n",
    "    ''' Measure the classification accuracy of some predictions (softmax outputs) \n",
    "    and labels (integer class labels)'''\n",
    "    return np.sum(np.argmax(predictions,axis=1).flatten()==labels.flatten())/batch_size\n",
    "\n",
    "test_accuracy_over_time = []\n",
    "train_loss_over_time = []\n",
    "for epoch in range(NUM_EPOCHS):\n",
    "    train_loss = []\n",
    "    \n",
    "    # Training Phase \n",
    "    for step in range(train_inputs.shape[0]//batch_size):\n",
    "        # Creating one-hot encoded labels with labels\n",
    "        # One-hot encoding dight 3 for 10-class MNIST data set will result in\n",
    "        # [0,0,0,1,0,0,0,0,0,0]\n",
    "        labels_one_hot = np.zeros((batch_size, num_labels),dtype=np.float32)\n",
    "        labels_one_hot[np.arange(batch_size),train_labels[step*batch_size:(step+1)*batch_size]] = 1.0\n",
    "        \n",
    "        # Printing the one-hot labels\n",
    "        if epoch ==0 and step==0:\n",
    "            print('Sample labels (one-hot)')\n",
    "            print(labels_one_hot[:10])\n",
    "            print()\n",
    "        \n",
    "        # Running the optimization process\n",
    "        loss, _ = session.run([tf_loss,tf_loss_minimize],feed_dict={\n",
    "            tf_inputs: train_inputs[step*batch_size: (step+1)*batch_size,:],\n",
    "            tf_labels: labels_one_hot}\n",
    "                             )\n",
    "        train_loss.append(loss) # Used to average the loss for a single epoch\n",
    "        \n",
    "    test_accuracy = []\n",
    "    # Testing Phase\n",
    "    for step in range(test_inputs.shape[0]//batch_size):\n",
    "        test_predictions = session.run(tf_predictions,feed_dict={tf_inputs: test_inputs[step*batch_size: (step+1)*batch_size,:]})\n",
    "        batch_test_accuracy = accuracy(test_predictions,test_labels[step*batch_size: (step+1)*batch_size])        \n",
    "        test_accuracy.append(batch_test_accuracy)\n",
    "    \n",
    "    print('Average train loss for the %d epoch: %.3f\\n'%(epoch+1,np.mean(train_loss)))\n",
    "    train_loss_over_time.append(np.mean(train_loss))\n",
    "    print('\\tAverage test accuracy for the %d epoch: %.2f\\n'%(epoch+1,np.mean(test_accuracy)*100.0))\n",
    "    test_accuracy_over_time.append(np.mean(test_accuracy)*100)\n",
    "    \n",
    "session.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualizing the loss and Accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\nkEtiT58+naeffjrfYYiIiIhIjpnZf/Mdg+SH5vgiIiIiQ1Omc3y1ExERERERERERERGRgqUktoiI\niIiIiIiIiIgULCWxRURERERERERERKRgKYktIiIiIiIiIiIiIgVLSWwRERERERERERERKVhKYouI\niIiIiIiIiIhIwVISW0REREREREREREQKlpLYIiIiIiIiIiIiIlKwlMQWERERERERERERkYJVku8A\nBrt7X1jKqIpSPjRjTL5DERERERERERGRftTV7TS2ddLY1klTWyerW9f+3NjaSZd7xscyIF5azMjy\nEkaUllBZXkJlWXQrL6GspLjXx7s7ze1dNEZxNEVxNUaxtHd19/HVysYoNqOyvIQR0d9yZNLPlWUl\nFBdZvkMclJTE7qNL5rzKNpOqlMQWERERERERESlA3d1Oc0cXja3rJnnX/txBU3vXOong9ZLC0WNa\nOroGLO5Ysa1JaI8oLaGspIim9q41CfPG9k6yyJlLgYjHitf5wqK0pLAaZdx+2mzMCi/RriR2H1VX\nxKhv6ch3GCIiIiIiIiIig4q7U9fcwTsNrbzT0Mry+laWN7TRkUUFcZc7zW2dNLZ10djWESWcu0Ji\nui1UKTdlmOxNThpXlsWoLCtmdGUp08eMoLKsOEo6xhhRFqqnk38eURYSzbHizBOS3VEl9YYS501t\nnaxu66Sts5vJo4rXVG2PLIsqfJMruKNtI8tDctQovGTkUNfR1U1T+/qV+uHvu/7ntKNL30RkQkns\nPqqOx3ivsT3fYYiIiIiIiIgMC13dznuNbbzT0EpntzO+qpxxI8uySh5K9rq7nVXN7bxT35pVMZ87\nrG7tYFl9K8ujZPWan+tbaetcP2GdTbsFg3VaNYwoK6Y6HmNKTZwRZcVrktHrtXdYkwgOiehM2neI\nSP4oid1HNfEYS95tyncYIiIiIiIiIoNea0cX79RHVblRkjM5+bm8vpUVq9vo7F63ctEMxlSWMaGq\nnAnV5evdj4/uR5RmnqTsdmhuX7/38XotKdrDfWeXM21MBTPGVjJjXCVTN6mgJEeJde/nnhHtXd2s\naGhb8z6/U9+65u+QuF/R0NbnHsulxUWMry5jYlWcD06p4cBtyphQHY/+TmXRFxLlBddeQUTyT0ns\nPqqpKKWuWZXYIiIiIiIiIplwd1Y2trNoRSOL3m1k8YpGFr/byKIVjSyrb11v/IjS4pCQri5njy1G\n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\n5TWpmakTmijqQUqSJGmM6ejcQFNDsMsUa2JLkiSNBqUmsSPieODfgEbga5n52X77JwDfAA4DHgX+\nPDOXjXScqj8TmhrZa9fJ7LXr5AH3d27YzKq1Xaxcu5FV67pYtW4jK9dW3let7eLmh9awcm0XXZt7\nBzy+sSGY1tpUldhuKT43MX1iC1Nbm5g0oYnJLY1MamliyoQmJk1oZHJLE5NaGpk8ofI+oanBZLgk\nSdIIa+/sYs60VhotNydJkjQqlJbEjohG4EzgZcBDwHURcWG/mnjvAB7PzH0i4mTgc8Cfj3y0Gm/6\nks/7zpm61T6ZybqN3axau5HV6zbSuWEzazdspnPDZtZs2ETnhs10buhmzfpNdK7fxPJHnyzaNtOb\nWz3t0zQ2BJNaGpnY3EhrcyOtzQ2V96ZGJhSfJ1a3NzfS2tRAc2MDzcV7S2PQ3NhAU2MDzY1BS2PV\n/oaguamBxoagqSGK98r209u27GtoqMTVEJVX5TMm2yVJUt3o6OxirqVEJEmSRo0yZ2IfASzNzPsA\nIuK7wElAdRL7JOBjxecfAP8ZEZGZg0wBSsMnIpjW2sy01mb2mT1l0Mf19ibrN/ewflM36zf28OSm\nbp4s3tc/9d7Nk5sqfZ7c2EPX5r5XLxuKz2u7ulm9buNT7V3dW/qUIQIaI2hoiMp7UPn8VMK78mfW\nEDyVAI+nPvO07S3vQQANDRBsOcdT+6m8U/nf044PiveiXzzVZ8s2fX2e2h9PXavvnLD1c1B9nafO\nWX3totPTjn16n74e/X8J0BcPTzum6nPxoeoSA/Z/+vaWa/TvQ/X5Bjhma+esjqW/p/UZ4NpPu/5W\n+m/tdyPV1+zfpf8xz9z/zD/rbfXv32H713tm0Fv9OWo91yDPs+V8W7k3W+2/lR019B3o56/13JX+\ntR1Qy8+0tRi3HktN3Ws8e+3nr+UKwx37C/ebRWtzY41HSaNfR2cXz95tWtlhSJIkqVBmEnt34MGq\n7YeA52+tT2Z2R0QnsAvwyIhEKA2DhoZgyoRKCRG2PtF7h2Um3b3J5p5eNncnm3t7n/q8qaeX7t4t\nnzcXr57epKe3ctyW9166e5LerGrvqbz3ZKW9tzfp6YWeTDK37MvkqXNmJr1JpX9SbG9py6p9vb1J\nkvT2Unkv+vf1SXhmW9W+7IUeerf0AbL/Z7Joo2jL4s9ty76+81V2bOk30Dmo2tf/PNVtFG3FKbdc\n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\nvGu3AAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x2689d6e27b8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x_axis = np.arange(len(train_loss_over_time))\n",
    "\n",
    "fig, ax = plt.subplots(nrows=1, ncols=2)\n",
    "fig.set_size_inches(w=25,h=5)\n",
    "ax[0].plot(x_axis, train_loss_over_time)\n",
    "ax[0].set_xlabel('Epochs',fontsize=18)\n",
    "ax[0].set_ylabel('Average train loss',fontsize=18)\n",
    "ax[0].set_title('Training Loss over Time',fontsize=20)\n",
    "ax[1].plot(x_axis, test_accuracy_over_time)\n",
    "ax[1].set_xlabel('Epochs',fontsize=18)\n",
    "ax[1].set_ylabel('Test accuracy',fontsize=18)\n",
    "ax[1].set_title('Test Accuracy over Time',fontsize=20)\n",
    "fig.savefig('mnist_stats.jpg')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
